package cn.cellcom.adapter.service;

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.cellcom.agent.biz.Org00Biz;
import cn.cellcom.agent.biz.TButtonBiz;
import cn.cellcom.agent.biz.TChannelBiz;
import cn.cellcom.agent.biz.TCrmBiz;
import cn.cellcom.agent.biz.TGroupBiz;
import cn.cellcom.agent.biz.TLwBiz;
import cn.cellcom.agent.biz.TQuestionBiz;
import cn.cellcom.agent.biz.TSessionBiz;
import cn.cellcom.agent.biz.TSettingBiz;
import cn.cellcom.agent.common.AgentConstant;
import cn.cellcom.agent.common.AgentConstant.WECHAT_STEP;
import cn.cellcom.agent.common.AgentEnv;
import cn.cellcom.agent.entity.TSettingEntity;
import cn.cellcom.agent.online.client.ClientManager;
import cn.cellcom.agent.online.client.QqClient;
import cn.cellcom.agent.online.client.VisitorClient;
import cn.cellcom.agent.online.iq.ProcessorResult;
import cn.cellcom.agent.online.iq.agent.LwDetailProcessor;
import cn.cellcom.agent.online.iq.visitor.ButtonProcessor;
import cn.cellcom.agent.online.iq.visitor.GetGroupListProcessor;
import cn.cellcom.agent.online.iq.visitor.LwProcessor;
import cn.cellcom.agent.online.iq.visitor.SatisfyProcessor;
import cn.cellcom.agent.online.iq.visitor.VisitorProcessors;
import cn.cellcom.agent.online.message.MessageConstant;
import cn.cellcom.agent.online.message.MessageConstant.MULIT_TYPE;
import cn.cellcom.agent.online.wrapper.SessionWrapper;
import cn.cellcom.agent.pojo.TChannel;
import cn.cellcom.agent.pojo.TCrm;
import cn.cellcom.agent.pojo.TGroup;
import cn.cellcom.agent.pojo.TOrg;
import cn.cellcom.agent.struts.form.VisitorForm;
import cn.cellcom.jar.biz.AbstractBiz;
import cn.cellcom.jar.file.FileProcessor;
import cn.cellcom.jar.file.IFileProcessor;
import cn.cellcom.jar.file.IFileProcessor.MODE;
import cn.cellcom.jar.util.DT;
import cn.cellcom.jar.util.MyException;
import cn.cellcom.rpc.entity.ChatMessage;
import cn.cellcom.rpc.entity.KfzhMessage;
import cn.cellcom.rpc.service.RpcService;
import net.sf.json.JSONObject;

public class GzhVisitorHandler implements RpcService {

	private Logger log = LoggerFactory.getLogger(this.getClass());

	private TSettingBiz sbiz;

	private TButtonBiz bbiz;

	private Org00Biz obiz;

	private TSessionBiz ssbiz;

	private TGroupBiz gbiz;

	private TQuestionBiz qbiz;

	private TCrmBiz cbiz;

	private TChannelBiz chbiz;

	private TLwBiz lbiz;

	public GzhVisitorHandler(TSettingBiz sbiz, TButtonBiz bbiz, Org00Biz obiz, TSessionBiz ssbiz, TGroupBiz gbiz,
			TQuestionBiz qbiz, TCrmBiz cbiz, TChannelBiz chbiz, TLwBiz lbiz) {
		this.sbiz = sbiz;
		this.bbiz = bbiz;
		this.obiz = obiz;
		this.ssbiz = ssbiz;
		this.gbiz = gbiz;
		this.qbiz = qbiz;
		this.cbiz = cbiz;
		this.chbiz = chbiz;
		this.lbiz = lbiz;
	}

	private void error(String pid, String cid) {
		log.error("Create error for cid " + cid);
		QqClient visitorClient = (QqClient) ClientManager.getInstance().getClient(cid);
		visitorClient.getSessionByPid(pid).getSystem().sysSendText("输入的消息有误，请重新输入");
	}

	/**
	 * 登陆
	 * 
	 * @param cf
	 * @return
	 */
	private VisitorClient logon(VisitorForm cf) {
		TCrm crm = null;
		String httpSessionId = String.valueOf(System.currentTimeMillis());
		TOrg org = null;
		TSettingEntity setting = null;
		try {
			org = obiz.getByPid(cf.getPid());
			setting = sbiz.getChannelSetting(cf.getPid(), cf.getChannel(), false);
			crm = cbiz.getOrCreateCrm(null, null, cf, org, setting);
		} catch (MyException e) {
			log.error(cf.getTid() + " catch exception while logon.", e.getException());
			return null;
		}

		VisitorClient visitorClient = null;
		try {
			visitorClient = new VisitorClient(chbiz, ssbiz, gbiz, qbiz, cf.getChannel(), crm, httpSessionId);
			ClientManager.getInstance().record(visitorClient);
			log.info("[{}] have no client, so create it [{}], sequence[{}]", crm.getId(), visitorClient,
					visitorClient.getSequence());

			SessionWrapper sessionOfPid = visitorClient.getSessionByPid(cf.getPid());
			if (sessionOfPid == null) {
				sessionOfPid = visitorClient.initSession(cf.getPid(), setting, "wechat", null);
				sessionOfPid.setSetting(setting);
			} else {
				log.info("[{}] have exist session[{}] for pid[{}]", crm.getId(), sessionOfPid.getId(), cf.getPid());
				sessionOfPid.setSetting(setting);
			}
			sessionOfPid.join(visitorClient, null);

			visitorClient.sendSession(sessionOfPid.getSession());
			visitorClient.notifyStatus(cf.getPid(), null);
		} catch (MyException e) {
			log.error("", e.getException());
		} catch (Exception e) {
			log.error("", e);
		}
		return visitorClient;
	}

	@Override
	public boolean kfzh(KfzhMessage kf, String appid) {
		return false;
	}

	@Override
	public boolean chat(ChatMessage text, String appid) {

		log.info("坐席收到访客的消息：[{}][{}][{}] from appid[{}] ", text.getCid(), text.getId(), text.getText(), appid);
		try {
			VisitorForm cf = new VisitorForm();
			cf.setId(text.getId());
			cf.setCid(text.getSender());
			TChannel channel = chbiz.getChannelByWcAppid(appid);
			cf.setChannel(channel.getNo());
			cf.setPid(channel.getPid());

			VisitorClient visitorClient = (VisitorClient) ClientManager.getInstance().getClient(cf.getCid());
			// 首次发送消息
			if (visitorClient == null || visitorClient.getSessionByPid(cf.getPid()) == null) {
				visitorClient = logon(cf);
				visitorClient.setWechatStep(WECHAT_STEP.INIT);
			} else {// 每次消息都设置active，保活
				visitorClient.setLastActiveGet();
			}

			String content = saveMulti(text, visitorClient.getCrm(), cf);
			// 处于初始化
			if (content.equals("88") && !WECHAT_STEP.INIT.equals(visitorClient.getWechatStep())) {// 收到结束会话,并且不处于初始化
				cf.setEvent(MessageConstant.MESSAGE_EVENT.END_SESSION.name());
				visitorClient.setWechatStep(WECHAT_STEP.INIT);
			} else if (visitorClient.getWechatStep().equals(WECHAT_STEP.INIT)) {
				cf.setEvent(MessageConstant.MESSAGE_EVENT.GET_GROUP.name());
				// 当前处于选择技能组的状态，那么就执行进入技能组
			} else if (visitorClient.getWechatStep().equals(WECHAT_STEP.GET_GROUP)) {
				String group = visitorClient.getWechatGroupIndex().get(content);
				if (group == null) {
					error(cf.getPid(), cf.getCid());
					return false;
				} else {
					cf.setValue(group);
					cf.setEvent(MessageConstant.MESSAGE_EVENT.ENTER_GROUP.name());
				}
				// 当前处于技能组的状态，那么久可以进入聊天了
			} else if (visitorClient.getWechatStep().equals(WECHAT_STEP.IN_GROUP)) {
				SessionWrapper session = visitorClient.getSessionByPid(cf.getPid());
				if (content.equals("66")
						&& session.getSession().getStep().equals(AgentConstant.SESSION_STEP.SELF.name())) {// 进入人工
					cf.setEvent(MessageConstant.MESSAGE_EVENT.ENTER_GROUP.name());
				} else {
					cf.setEvent(MessageConstant.MESSAGE_EVENT.CHAT.name());
					cf.setValue(content);
				}
			}

			log.info("Handle wechat message[{}] use Event[{}]", text.getId(), cf.getEvent());
			Map<String, AbstractBiz> bizs = new HashMap<String, AbstractBiz>();
			if (SatisfyProcessor.NAME.equals(cf.getEvent())) {
				bizs.put("ssbiz", ssbiz);
				bizs.put("sbiz", sbiz);
			} else if (ButtonProcessor.NAME.equals(cf.getEvent())) {
				bizs.put("bbiz", bbiz);
			} else if (GetGroupListProcessor.NAME.equals(cf.getEvent())
					|| MessageConstant.MESSAGE_EVENT.ENTER_GROUP.name().equals(cf.getEvent())) {
				bizs.put("gbiz", gbiz);
				bizs.put("chbiz", chbiz);
			} else if (LwProcessor.NAME.equals(cf.getEvent())) {
				/*
				 * try { TLw lw = new TLw(); CopyUtil.copy(req, lw, null, false);
				 * cf.setObject(lw); } catch (MyException e) { }
				 */
				bizs.put("sbiz", ssbiz);
			} else if (LwDetailProcessor.NAME.equals(cf.getEvent())) {
				bizs.put("lbiz", lbiz);
			} else if (cf.getEvent().equals(MessageConstant.MESSAGE_EVENT.GET_GROUP.name())) {
				visitorClient.getWechatGroupIndex().clear();
			}
			ProcessorResult result = VisitorProcessors.createProcessors().process(bizs, visitorClient, cf);
			if (result != null) {
				Object dt = result.getData();
				if (dt == null) {
					dt = "";
				}
				if (StringUtils.isNotBlank(cf.getEvent())) {
					log.info("[{}] <IQ_MESSAGE> handle result : " + cf.getEvent() + "[{}]", visitorClient.getId(), dt);
				}
				if (result.isSuccess()) {
					// 获取技能组列表
					if (cf.getEvent().equals(MessageConstant.MESSAGE_EVENT.GET_GROUP.name())) {
						visitorClient.setWechatStep(WECHAT_STEP.GET_GROUP);

						Map map = (Map) dt;
						StringBuffer sb = new StringBuffer(String.valueOf(map.get("title")));
						List<TGroup> list = (List<TGroup>) map.get("list");
						for (int i = 0; i < list.size(); i++) {
							TGroup g = list.get(i);
							String index = String.valueOf(i + 1);
							visitorClient.getWechatGroupIndex().put(index, g.getId());
							sb.append("\r\n").append(index).append(" ").append(g.getName());
						}
						visitorClient.getSessionByPid(cf.getPid()).getSystem().sysSendText(sb.toString());
					} else if (MessageConstant.MESSAGE_EVENT.ENTER_GROUP.name().equals(cf.getEvent())) {
						visitorClient.setWechatStep(WECHAT_STEP.IN_GROUP);
					}
				} else {
					error(cf.getPid(), cf.getCid());
					return false;
				}
			} else {
				log.error("[{}] <IQ_MESSAGE> send fail for event[{}]", visitorClient.getId(), cf.getEvent());
				error(cf.getPid(), cf.getCid());
				return false;
			}
		} catch (MyException e) {
			log.error("", e.getException());
		} catch (Exception e) {
			log.error("", e);
		}
		return true;

	}

	/**
	 * 
	 * @param text
	 * @param crm
	 * @param cf
	 * @return
	 */
	private String saveMulti(ChatMessage text, TCrm crm, VisitorForm cf) {
		if (MULIT_TYPE.AUDIO.toString().equals(text.getMultiType())) {
			cf.setMultiType(MULIT_TYPE.AUDIO.toString());
			String file = AgentEnv.CHAT_FILE_PATH + crm.getOrg() + "/" + DT.getYYYYMMDD() + "/" + text.getText();
			try {
				IFileProcessor ifp = new FileProcessor();
				ifp.copyF2F(AgentEnv.WECHAT_TEMP_PATH + text.getText(), file, MODE.WRITE_CREATE_MODE);
				ifp.deleteFile(AgentEnv.WECHAT_TEMP_PATH + text.getText());
			} catch (MyException e) {
				log.error("", e.getException());
			}
			Map<String, Object> v = new HashMap<String, Object>();
			v.put("date", DT.getYYYYMMDD());
			v.put("overdue", DT.getYYYYMMDDHHMMSS(DT.getNextDay(7)));
			v.put("newName", text.getText());
			v.put("oldName", "微信语音");
			v.put("multiType", MULIT_TYPE.AUDIO.toString());
			v.put("size", (new File(AgentEnv.WECHAT_TEMP_PATH + text.getText())).getTotalSpace());
			v.put("duration", 0);
			return JSONObject.fromObject(v).toString();
		} else if (MULIT_TYPE.IMG.toString().equals(text.getMultiType())) {
			cf.setMultiType(MULIT_TYPE.FILE.toString());
			String file = AgentEnv.CHAT_FILE_PATH + crm.getOrg() + "/" + DT.getYYYYMMDD() + "/" + text.getText();
			try {
				IFileProcessor ifp = new FileProcessor();
				ifp.copyF2F(AgentEnv.WECHAT_TEMP_PATH + text.getText(), file, MODE.WRITE_CREATE_MODE);
				ifp.deleteFile(AgentEnv.WECHAT_TEMP_PATH + text.getText());
			} catch (MyException e) {
				log.error("", e.getException());
			}
			Map<String, Object> v = new HashMap<String, Object>();
			v.put("date", DT.getYYYYMMDD());
			v.put("overdue", DT.getYYYYMMDDHHMMSS(DT.getNextDay(7)));
			v.put("newName", text.getText());
			v.put("oldName", "微信图片");
			v.put("multiType", MULIT_TYPE.IMG.toString());
			v.put("size", (new File(AgentEnv.WECHAT_TEMP_PATH + text.getText())).getTotalSpace());
			return JSONObject.fromObject(v).toString();
		} else if (MULIT_TYPE.MAP.toString().equals(text.getMultiType())) {
			cf.setMultiType(MULIT_TYPE.MAP.toString());
			return text.getText();
		}

		return text.getText();
	}

}
